package com.tbit.uqbike.service.business.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.tbit.uqbike.constant.*;
import com.tbit.uqbike.manager.exception.BaseException;
import com.tbit.uqbike.object.business.Point;
import com.tbit.uqbike.object.pojo.*;
import com.tbit.uqbike.object.pojo.dto.AfterSaleContactDTO;
import com.tbit.uqbike.object.pojo.dto.EditGiftCardExpireDateDTO;
import com.tbit.uqbike.object.pojo.dto.UpdateBlackListDTO;
import com.tbit.uqbike.object.pojo.vo.*;
import com.tbit.common.entity.view.Result;
import com.tbit.uqbike.quartz.*;
import com.tbit.uqbike.service.base.CalibrateService;
import com.tbit.uqbike.service.base.ParkPointService;
import com.tbit.uqbike.service.base.RedisService;
import com.tbit.uqbike.service.business.SupportService;
import com.tbit.uqbike.webmanager.dao.core.*;
import com.tbit.uqbike.webmanager.dao.log.*;
import com.tbit.uqbike.webmanager.util.StringUtils;
import com.tbit.uqbike.webmanager.util.adaPay.AdaPayUtil;
import com.tbit.uqbike.webmanager.util.excel.ExcelUtil;
import com.tbit.utils.Assert;
import com.tbit.utils.GeoUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 额外功能接口实现类
 *
 * @Author:BUGTian
 * @DATE: 2022/6/10
 */
@Service
@Slf4j
public class SupportServiceImpl implements SupportService {
    private static final String VIRTUAL_RECHARGE_FUNCTION_KEY = "VIRTUAL_RECHARGE_FUNCTION";
    @Autowired
    private ActivityQuartz activityQuartz;
    @Autowired
    private BirthGiveQuartz birthGiveQuartz;
    @Autowired
    private ClearExpireCouponQuartz clearExpireCouponQuartz;
    @Autowired
    private LowBatteryReminderQuartz lowBatteryReminderQuartz;
    @Autowired
    private PointQuartz pointQuartz;
    @Autowired
    private ReconciliationQuartz reconciliationQuartz;
    @Autowired
    private SubAccountQuartz subAccountQuartz;
    @Autowired
    private SundryDataQuartz sundryDataQuartz;
    @Autowired
    private FinancialStatisticsQuartz financialStatisticsQuartz;
    @Autowired
    private GiftCardUserDao giftCardUserDao;
    @Autowired
    private AccountUserDao accountUserDao;
    @Autowired
    private VipCardDao vipCardDao;
    @Autowired
    private UserDao userDao;
    @Autowired
    private AccountDao accountDao;
    @Autowired
    private CouponMealDao couponMealDao;
    @Autowired
    private ActivityDetailDao activityDetailDao;
    @Autowired
    private RechargeGiveDao rechargeGiveDao;
    @Autowired
    private NewUserActivityDao newUserActivityDao;
    @Autowired
    private UserRefundLogDao userRefundLogDao;
    @Autowired
    private BrandRemoteConfigDao brandRemoteConfigDao;
    @Autowired
    private GiftCardDao giftCardDao;
    @Autowired
    private ViolationLogDao violationLogDao;
    @Autowired
    private MachineCleanLogDao machineCleanLogDao;
    @Autowired
    private MachineNeatLogDao machineNeatLogDao;
    @Autowired
    private PatrolLogDao patrolLogDao;
    @Autowired
    private ParkPointApplyDao parkPointApplyDao;
    @Autowired
    private CalibrateService calibrateService;
    @Autowired
    private ParkPointDao parkPointDao;
    @Autowired
    private ParkFeatureDao parkFeatureDao;
    @Autowired
    private AdaccountDao adaccountDao;
    @Autowired
    private UserBlackListDao userBlackListDao;
    @Autowired
    private UsermsgDao usermsgDao;
    @Autowired
    private RedisService redisService;
    @Autowired
    private ParkPointService parkPointService;

    @Override
    public Result executeTask(String className, String methodName) {
        return executeMethod(classChoose(className), methodName);
    }

    @Override
    public List<UserGiftCardAreaVO> getUserGiftCardRecommendArea(Integer userId) {
        Map<Integer, Integer> map = new HashMap<>();
        //推荐区域
        List<UserGiftCardAreaVO> list = giftCardUserDao.getUserGiftCardRecommendArea(userId);
        for (UserGiftCardAreaVO userGiftCardAreaVO : list) {
            map.put(userGiftCardAreaVO.getAccountId(), 1);
        }
        User user = userDao.getByUserId(userId);
        //品牌id
        Integer accountId = user.getAccountId();
        List<AreaVO> areaByBrandId = accountDao.getAreaByBrandId(accountId);
        for (AreaVO areaVO : areaByBrandId) {
            //去重
            if (map.get(areaVO.getAccountId()) != null) {
                continue;
            }
            list.add(new UserGiftCardAreaVO()
                    .setAccountId(areaVO.getAccountId())
                    .setAreaName(areaVO.getName())
                    .setUserId(userId).setAreaType(0));
        }
        return list;
    }

    @Override
    public Result<List<AccountUser>> queryAccountUserByBrandId(Integer brandId) {
        List<AccountUser> list = accountUserDao.queryAccountUserByBrandId(brandId);
        return Result.success(list);
    }

    @Override
    public Result editVipCardExpireDate(String orderNO, String oldExpireDate, String newExpireDate) {
        log.info("会员卡置为失效,订单编号：{},旧失效时间为：{},新失效时间为：{}", orderNO, oldExpireDate, newExpireDate);
        vipCardDao.updateValid(orderNO);
        return Result.success();
    }

    @Override
    public CouponCheckVO deleteCouponCheck(Integer couponId) {
        //查询优惠券绑定的活动名称和区域
        List<ActivityNameVO> activityNameList = activityDetailDao.queryActivityNameListByCouponId(couponId);
        //查询优惠券绑定的优惠券套餐名称和区域
        List<CouponMealNameVO> couponMealNameList = couponMealDao.queryCouponMealNameListByCouponId(couponId);
        //查询优惠券绑定了赠送配置的区域
        List<RechargeGiveNameVO> rechargeGiveNameList = rechargeGiveDao.queryRechargeGiveNameListByCouponId(couponId);
        //查询优惠券绑定了新用户赠送配置的区域
        List<NewUserActivityNameVO> newUserActivityNameList = newUserActivityDao.queryNewUserActivityNameListByCouponId(couponId);
        return new CouponCheckVO().setActivityNameList(activityNameList)
                .setCouponMealNameList(couponMealNameList)
                .setRechargeGiveNameList(rechargeGiveNameList)
                .setNewUserActivityNameList(newUserActivityNameList);
    }

    @Override
    public List<UserRefundLogVO> queryUserRefundLogByOrderNO(String orderNO) {
        List<UserRefundLogVO> list = userRefundLogDao.queryUserRefundLogByOrderNO(orderNO);
        return list;
    }

    @Override
    public Result editRushPayFeeConfig(RushPayFeeConfig rushPayFeeConfig, Integer accountId) {
        checkRushPayFeeConfig(rushPayFeeConfig);
        List<BrandRemoteConfig> brandRemoteConfigs = brandRemoteConfigDao.selectBrandRemoteConfigList(new BrandRemoteConfig(accountId, BrandRemoteConfigConstant.RUSH_PAY_FEE));
        //设置入库属性
        BrandRemoteConfig brandRemoteConfig = new BrandRemoteConfig(accountId, BrandRemoteConfigConstant.RUSH_PAY_FEE, rushPayFeeConfig.toRushPayFeeConfigStr());
        if (brandRemoteConfigs != null && brandRemoteConfigs.size() > 0) {
            //配置已存在，更新
            brandRemoteConfigDao.updateBrandRemoteConfig(brandRemoteConfig);
            redisService.del(RedisConstant.BRANDREMOTECONFIG_KEY_PREFIX + brandRemoteConfig.getAccountId());
        } else {
            //配置不存在，插入
            brandRemoteConfigDao.insertBrandRemoteConfig(brandRemoteConfig);
        }
        return Result.success();
    }

    @Override
    public RushPayFeeConfig queryRushPayFeeConfig(Integer accountId) {
        List<BrandRemoteConfig> brandRemoteConfigs = brandRemoteConfigDao.selectBrandRemoteConfigList(new BrandRemoteConfig(accountId, BrandRemoteConfigConstant.RUSH_PAY_FEE));
        if (brandRemoteConfigs != null && brandRemoteConfigs.size() > 0) {
            String paramKV = brandRemoteConfigs.get(0).getParamKV();
            return new RushPayFeeConfig().getRushPayFeeConfigByStr(paramKV);
        }
        return new RushPayFeeConfig(0, null, null, 0, null, null);
    }

    @Override
    public Result editGiftCardExpireDate(EditGiftCardExpireDateDTO editGiftCardExpireDateDTO) {
        GiftCard giftCard = giftCardDao.queryByCardNO(editGiftCardExpireDateDTO.getCardNO());
        if (giftCard == null) {
            return Result.error("礼品卡不存在");
        }
        if (giftCard.getUseTime() != null) {
            //已被使用
            return Result.error("礼品卡已被使用");
        }
        if (giftCard.getExpireDate().getTime() < System.currentTimeMillis()) {
            return Result.error("礼品卡已失效，无需重复操作");
        }
        giftCardDao.editGiftCardExpireDate(editGiftCardExpireDateDTO);
        return Result.success();
    }

    @Override
    public Result rejectControl(Integer logId, Integer type) {
        if (logId == null || type == null) {
            return Result.error("参数有误");
        }
        int updateCount = 0;
        switch (type) {
            case 1:
                //举报管理
                updateCount = violationLogDao.reject(logId);
                break;
            case 2:
                //清洁上报
                updateCount = machineCleanLogDao.reject(logId);
                break;
            case 3:
                //摆车上报
                updateCount = machineNeatLogDao.reject(logId);
                break;
            case 4:
                //巡检上报
                updateCount = patrolLogDao.reject(logId);
                break;
            default:
                return Result.error("类型有误");
        }
        if (updateCount < 1) {
            return Result.error("记录不存在");
        }
        return Result.success();
    }

    @Override
    public List<ParkPointApply> queryNearByParkPointApply(Integer adAccountId, Double lat, Double lon, Integer distance, Integer mapType) {
        if (mapType == null) {
            mapType = SysConstant.GOOGLE;
        }
        //查询未审核站点
        List<ParkPointApply> list = parkPointApplyDao.selectByAdAccountId(adAccountId);
        //经纬度校准并移除范围外的站点
        list = calibrateService.calibrateParkPointApplyAndRemove(list, mapType, lat, lon, distance);
        return list;
    }

    @Override
    public Result batchUpdateParkPointAllowRangeAndCapacity(MultipartFile file, Integer adAccountId, Integer mapType) {
        if (file == null || adAccountId == null) {
            return Result.error("参数有误");
        }
        List<BatchUpdateParkPoint> updateList = new ArrayList<>();
        List<BatchUpdateParkPoint> failList = new ArrayList<>();
        Workbook wb;
        try {
            wb = WorkbookFactory.create(Objects.requireNonNull(AdaPayUtil.MultipartFileToFile(file)));
            //站点名称index
            Integer siteNameIndex = null;
            //误差范围index
            Integer allowRangeIndex = null;
            //站点容量index
            Integer capacityIndex = null;
            //站点运营开关index
            Integer operateIndex = null;

            Integer pointsIndex = null;

            Integer highAllowRangeIndex = null;
            Sheet sheet = wb.getSheetAt(0);
            boolean flag = true;
            for (Row row : sheet) {
                if (flag) {
                    //第一行为标题
                    Iterator<Cell> cellIterator = row.cellIterator();
                    while (cellIterator.hasNext()) {
                        Cell cell = cellIterator.next();
                        log.info(cell.getStringCellValue());
                        if ("站点名称".equals(cell.getStringCellValue())) {
                            siteNameIndex = cell.getColumnIndex();
                        }
                        if ("误差范围".equals(cell.getStringCellValue())) {
                            allowRangeIndex = cell.getColumnIndex();
                        }
                        if ("站点容量".equals(cell.getStringCellValue())) {
                            capacityIndex = cell.getColumnIndex();
                        }
                        if ("营运开关".equals(cell.getStringCellValue())) {
                            operateIndex = cell.getColumnIndex();
                        }
                        if ("站点经纬度集合".equals(cell.getStringCellValue())) {
                            pointsIndex = cell.getColumnIndex();
                        }
                        if ("高精度误差范围(cm)".equals(cell.getStringCellValue())) {
                            highAllowRangeIndex = cell.getColumnIndex();
                        }
                    }
                    if (siteNameIndex == null || allowRangeIndex == null || capacityIndex == null || operateIndex == null || pointsIndex == null || highAllowRangeIndex == null) {
                        return Result.error("excel文件表头数据有误");
                    }
                    flag = false;
                    continue;
                }
                //后面的为数据
                String points = row.getCell(pointsIndex).toString();
                String name = row.getCell(siteNameIndex).toString();
                int allowRange = Double.valueOf(row.getCell(allowRangeIndex).toString()).intValue();
                int capacity = Double.valueOf(row.getCell(capacityIndex).toString()).intValue();
                int highAllowRange = Double.valueOf(row.getCell(highAllowRangeIndex).toString()).intValue();
                Boolean operateSwitch = Objects.equals("开启", StringUtils.trim(row.getCell(operateIndex).toString()));
                BatchUpdateParkPoint batchUpdateParkPoint = new BatchUpdateParkPoint(adAccountId, name, allowRange, capacity, operateSwitch, points, highAllowRange);
                updateList.add(batchUpdateParkPoint);
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Result.error("请检查文件excel是否有误");
        }
        if (updateList.size() < 1) {
            return Result.error("需要更新的数据不能为空");
        }

        //高精度判断
        for (BatchUpdateParkPoint batchUpdateParkPoint : updateList) {
            String pointsStr = batchUpdateParkPoint.getPoints();
            parkPointService.checkPoints(pointsStr);
            Integer siteType = parkPointService.getSiteType(pointsStr);
            parkPointService.checkHighPrecisionAllowRange(batchUpdateParkPoint.getHighPrecisionAllowRange());

            batchUpdateParkPoint.setSiteType(siteType);


            if (MapConstant.MAP_ORI.equals(mapType)) {
                List<Point> points = GeoUtil.getPoints(pointsStr);
                List<Point> pointCs = new ArrayList<Point>();
                for (Point point : points) {
                    pointCs.add(calibrateService.commonCalibrate(point, MapConstant.MAP_ORI, MapConstant.MAP_GOOGLE));
                }
                batchUpdateParkPoint.setPoints(GeoUtil.getPointToString(points));
                batchUpdateParkPoint.setPointsC(GeoUtil.getPointToString(pointCs));
            } else {
                List<Point> points = new ArrayList<Point>();
                List<Point> pointCs = GeoUtil.getPoints(pointsStr);
                for (Point point : pointCs) {
                    points.add(calibrateService.commonCalibrate(point, MapConstant.MAP_GOOGLE, MapConstant.MAP_ORI));
                }
                batchUpdateParkPoint.setPoints(GeoUtil.getPointToString(points));
                batchUpdateParkPoint.setPointsC(GeoUtil.getPointToString(pointCs));
            }

        }

        for (BatchUpdateParkPoint batchUpdateParkPoint : updateList) {
            if (batchUpdateParkPoint.getAllowRange() == null || batchUpdateParkPoint.getCapacity() == null) {
                failList.add(batchUpdateParkPoint);
                continue;
            }

            //更新站点容量和误差范围
            int count = parkPointDao.updateByNameAndAccountId(batchUpdateParkPoint);
            if (count < 1) {
                //更新失败
                failList.add(batchUpdateParkPoint);
            }
        }
        //部分更新成功
        if (failList.size() > 0) {
            //移除更新失败的
            updateList.removeAll(failList);
            Map<String, Object> resultMap = new HashMap<>();
            List<String> successList = updateList.stream().map(BatchUpdateParkPoint::getSiteName).collect(Collectors.toList());
            resultMap.put("success", successList);
            resultMap.put("successCount", successList.size());
            List<String> errorList = failList.stream().map(BatchUpdateParkPoint::getSiteName).collect(Collectors.toList());
            resultMap.put("error", errorList);
            resultMap.put("errorCount", errorList.size());
            return Result.successCode("部分更新成功", resultMap, 201);
        }
        return Result.success();
    }

    @Override
    public Result getBatchUpdateParkPointTemplate(Integer adAccountId, Integer type, Integer mapType) {
        if (adAccountId == null || type == null) {
            return Result.error("参数有误");
        }
        ExcelUtil<BatchUpdateParkPoint> excelUtil = new ExcelUtil<>(BatchUpdateParkPoint.class);
        List<BatchUpdateParkPoint> list = new ArrayList<>();
        switch (type) {
            case 0:
                //空模板
                break;
            case 1:
                list = parkPointDao.getBatchUpdateByAdAccountId(adAccountId);
            default:
                break;
        }

        list.forEach(v -> {
            if (MapConstant.MAP_ORI.equals(mapType)) {
                v.setExportPoints(v.getPoints());
            } else {
                v.setExportPoints(v.getPointsC());
            }
            if (v.getSiteType() == null) {
                v.setSiteType(0);
            }
            if (SiteTypeConstant.GENERAL_SITE.equals(v.getSiteType())) {
                v.setHighPrecisionAllowRange(0);
            }
        });

        return Result.success(excelUtil.exportExcel(list, "批量修改站点信息模板").getData());
    }

    @Override
    public Result getBatchUpdateParkFeatureTemplate(Integer accountId, Integer type) {
        if (accountId == null || type == null) {
            return Result.error("参数有误");
        }
        ExcelUtil<BatchUpdateParkFeature> excelUtil = new ExcelUtil<>(BatchUpdateParkFeature.class);
        List<BatchUpdateParkFeature> list = new ArrayList<>();
        if (type != 0) {
            list = parkPointDao.getBatchUpdateParkFeatureByAdAccountId(accountId);
        }
        return Result.success(excelUtil.exportExcel(list, "批量修改站点功能模板").getData());
    }

    @Override
    public List<AdvertConfigAdAccount> queryAdvertConfigAdAccount(Integer accountId) {
        return adaccountDao.queryAdvertConfigAdAccount(accountId);

    }

    @Override
    public void deleteAdvertConfig(Integer accountId) {
        adaccountDao.deleteAdvertConfig(accountId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result editAfterSaleContact(AfterSaleContactDTO afterSaleContactDTO) {
        Integer accountId = afterSaleContactDTO.getAccountId();
        Assert.notNull(accountId, "参数有误");
        List<AfterSaleContact> afterSaleContactList = afterSaleContactDTO.getAfterSaleContactList();
        String data = "";
        if (CollectionUtil.isNotEmpty(afterSaleContactList)) {
            for (AfterSaleContact afterSaleContact : afterSaleContactList) {
                Assert.notNulls("缺少必要参数", afterSaleContact.getName(), afterSaleContact.getPhone(), afterSaleContact.getSort());
            }
            List<AfterSaleContact> sortList = ListUtil.sortByProperty(afterSaleContactList, "sort");
            int i = 0;
            //保持连续
            for (AfterSaleContact afterSaleContact : sortList) {
                if (afterSaleContact.getSort() != ++i) {
                    return Result.error("请保持显示顺序连续并且从1开始");
                }
            }
            data = JSON.toJSONString(sortList);
            if (data.length() > 400) {
                return Result.error("配置过多，请适当减少配置数量");
            }
        }
        BrandRemoteConfig brandRemoteConfig = new BrandRemoteConfig();
        brandRemoteConfig.setAccountId(accountId);
        brandRemoteConfig.setConfigType(BrandRemoteConfigConstant.AFTER_SALE_CONTACT);
        brandRemoteConfigDao.deleteBrandRemoteConfigById(brandRemoteConfig);
        redisService.del(RedisConstant.BRANDREMOTECONFIG_KEY_PREFIX + brandRemoteConfig.getAccountId());
        if (StringUtils.isNotEmpty(data)) {
            brandRemoteConfig.setParamKV(data);
            brandRemoteConfigDao.insertBrandRemoteConfig(brandRemoteConfig);
        }
        return Result.success();
    }

    @Override
    public Result<List<AfterSaleContact>> getAfterSaleContact(Integer accountId) {
        BrandRemoteConfig brandRemoteConfig = new BrandRemoteConfig();
        brandRemoteConfig.setAccountId(accountId);
        brandRemoteConfig.setConfigType(BrandRemoteConfigConstant.AFTER_SALE_CONTACT);
        List<BrandRemoteConfig> brandRemoteConfigs = brandRemoteConfigDao.selectBrandRemoteConfigList(brandRemoteConfig);
        if (CollectionUtil.isEmpty(brandRemoteConfigs)) {
            return Result.success(new ArrayList<>());
        }
        return Result.success(AfterSaleContact.parseList(brandRemoteConfigs.get(0).getParamKV()));
    }

    @Override
    public Result updateUserBlackList(UpdateBlackListDTO updateBlackListDTO) {
        userBlackListDao.updateUserBlackList(updateBlackListDTO);
        final UserBlackList userBlackList = new UserBlackList()
                .setAccountId(updateBlackListDTO.getAccountId())
                .setAddTime(updateBlackListDTO.getAddTime())
                .setIdNo(updateBlackListDTO.getIdNO())
                .setPhone(updateBlackListDTO.getPhone());
        UserBlackList userBlock = userBlackListDao.selectBy(userBlackList);
        if (Objects.nonNull(userBlock)) {
            Usermsg usermsg = new Usermsg();
            usermsg.setMsgtype(0);
            usermsg.setUserid(userBlock.getUserId());
            usermsg.setCreatetime(updateBlackListDTO.getAddTime());
            usermsg.setMsgstate(0);
            usermsg.setTitle("黑名单到期时间变更");
            usermsg.setContent("用户您好,您的账户黑名单到期时间调整（至" + DateUtil.formatDate(updateBlackListDTO.getExpireTime()) + "）");
            usermsgDao.insertSelective(usermsg);
        }
        return Result.success();
    }

    @Override
    public VirtualRechargeFunction queryVirtualRechargeFunction(Integer brandId) {
        VirtualRechargeFunction virtualRechargeFunction = new VirtualRechargeFunction(brandId, false, 1, null);
        String s = redisService.get(VIRTUAL_RECHARGE_FUNCTION_KEY + "_" + brandId);
        if (StringUtils.isNotEmpty(s)) {
            try {
                virtualRechargeFunction = JSON.parseObject(s, VirtualRechargeFunction.class);
            } catch (Exception e) {
                log.error("查询品牌虚拟充值功能配置JSON转换出错{}", s);
            }
        }
        return virtualRechargeFunction;
    }


    @Override
    public Result batchUpdateParkFeature(MultipartFile file, Integer accountId) {
        if (file == null || accountId == null) {
            return Result.error("参数有误");
        }
        Workbook wb;
        try {
            wb = WorkbookFactory.create(Objects.requireNonNull(AdaPayUtil.MultipartFileToFile(file)));
            //站点名称index
            Integer siteNameIndex = null;
            Integer bluetoothIndex = null;
            Integer bluetoothRssiValueIndex = null;
            Integer rfIdIndex = null;
            Integer footIndex = null;
            Integer cameraIndex = null;
            Integer parkFeatureTypePhoneIndex = null;
            Integer parkFeatureTypeCdzIndex = null;
            Sheet sheet = wb.getSheetAt(0);
            boolean flag = true;
            Map<String, Integer> pointMap = parkPointDao.getByAccountId(accountId).stream()
                    .collect(Collectors.toMap(ParkPoint::getName, ParkPoint::getParkPointId, (v1, v2) -> v2));
            if (pointMap.isEmpty()) {
                return Result.error("该运营区域下无站点,请添加后修改");
            }
            for (Row row : sheet) {
                if (flag) {
                    //第一行为标题
                    Iterator<Cell> cellIterator = row.cellIterator();
                    while (cellIterator.hasNext()) {
                        Cell cell = cellIterator.next();
                        log.info(cell.getStringCellValue());
                        if ("站点名称".equals(cell.getStringCellValue())) {
                            siteNameIndex = cell.getColumnIndex();
                        }
                        if ("蓝牙道钉".equals(cell.getStringCellValue())) {
                            bluetoothIndex = cell.getColumnIndex();
                        }
                        if ("RFID".equalsIgnoreCase(cell.getStringCellValue())) {
                            rfIdIndex = cell.getColumnIndex();
                        }
                        if ("脚撑".equals(cell.getStringCellValue())) {
                            footIndex = cell.getColumnIndex();
                        }
                        if ("摄像头".equals(cell.getStringCellValue())) {
                            cameraIndex = cell.getColumnIndex();
                        }
                        if ("蓝牙道钉Rssi值".equals(cell.getStringCellValue())) {
                            bluetoothRssiValueIndex = cell.getColumnIndex();
                        }
                        if ("手机拍照还车".equals(cell.getStringCellValue())) {
                            parkFeatureTypePhoneIndex = cell.getColumnIndex();
                        }
                        if ("充电桩".equals(cell.getStringCellValue())) {
                            parkFeatureTypeCdzIndex = cell.getColumnIndex();
                        }
                    }
                    if (siteNameIndex == null || bluetoothIndex == null || rfIdIndex == null || footIndex == null
                            || cameraIndex == null || bluetoothRssiValueIndex == null) {
                        return Result.error("excel文件表头数据有误");
                    }
                    flag = false;
                    continue;
                }
                String equalsVal = "开启";
                String siteName = row.getCell(siteNameIndex).toString();
                Integer pointId = pointMap.get(siteName.trim());
                if (pointId == null) {
                    continue;
                }
                //蓝牙
                String bluetoothRssiValue = Optional.ofNullable(row.getCell(bluetoothRssiValueIndex)).map(Objects::toString).orElse(null);
                int bluetoothVal = row.getCell(bluetoothIndex).toString().equals(equalsVal) ? 1 : 0;
                ParkFeature parkFeatureByBluetooth = new ParkFeature(pointId, 0, bluetoothVal);
                parkFeatureByBluetooth.setPropert(bluetoothRssiValue);
                //rfId
                int rfIdVal = row.getCell(rfIdIndex).toString().equals(equalsVal) ? 1 : 0;
                ParkFeature parkFeatureByRfId = new ParkFeature(pointId, 1, rfIdVal);
                //脚撑
                int footVal = row.getCell(footIndex).toString().equals(equalsVal) ? 1 : 0;
                ParkFeature parkFeatureByFoot = new ParkFeature(pointId, 3, footVal);
                //摄像头
                int cameraVal = row.getCell(cameraIndex).toString().equals(equalsVal) ? 1 : 0;
                ParkFeature parkFeatureByCameraVal = new ParkFeature(pointId, 4, cameraVal);
                //手机拍照还车
                int cameraValPhone = row.getCell(parkFeatureTypePhoneIndex).toString().equals(equalsVal) ? 1 : 0;
                ParkFeature parkFeatureTypePhone = new ParkFeature(pointId, 5, cameraValPhone);
                //充电桩
                int cdz = row.getCell(parkFeatureTypeCdzIndex).toString().equals(equalsVal) ? 1 : 0;
                ParkFeature parkFeatureTypeCdz = new ParkFeature(pointId, 6, cdz);

                List<ParkFeature> parkFeatures = new ArrayList<>();
                parkFeatures.add(parkFeatureByBluetooth);
                parkFeatures.add(parkFeatureByRfId);
                parkFeatures.add(parkFeatureByFoot);
                parkFeatures.add(parkFeatureByCameraVal);
                parkFeatures.add(parkFeatureTypePhone);
                parkFeatures.add(parkFeatureTypeCdz);
                parkFeatureDao.insertOrUpdateBatch(parkFeatures);
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Result.error("请检查文件excel是否有误");
        }

        return Result.success();
    }

    @Override
    public void updateVirtualRechargeFunction(VirtualRechargeFunction virtualRechargeFunction) {
        String key = VIRTUAL_RECHARGE_FUNCTION_KEY + "_" + virtualRechargeFunction.getBrandId();
        if (virtualRechargeFunction.getFlag()) {
            if (virtualRechargeFunction.getClosingTime() == null) {
                throw new BaseException("参数有误");
            }
            long time = System.currentTimeMillis();
            //开启,计算开关关闭时间
            long closingTime = virtualRechargeFunction.getClosingTime().getTime();
            long expTime = closingTime - time;
            if (expTime >= 0) {
                redisService.add(key, JSON.toJSONString(virtualRechargeFunction), expTime, TimeUnit.MILLISECONDS);
            } else {
                redisService.del(key);
            }
        } else {
            //关闭
            redisService.del(key);
        }
    }


    void checkRushPayFeeConfig(RushPayFeeConfig rushPayFeeConfig) {
        Date contactTime = rushPayFeeConfig.getContactTime();
        Date stopUsingTime = rushPayFeeConfig.getStopUsingTime();
        if (rushPayFeeConfig.getFlag() == null || contactTime == null || stopUsingTime == null || rushPayFeeConfig.getUsageFlag() == null || rushPayFeeConfig.getSimExpirationTime() == null || rushPayFeeConfig.getApiCount() == null) {
            throw new BaseException("参数有误");
        }
        long stopUsingTimes = stopUsingTime.getTime();
        long contactTimes = contactTime.getTime();
        if (stopUsingTimes < contactTimes) {
            throw new BaseException("暂停使用时间不能小于联系时间");
        }
        if (rushPayFeeConfig.getSimExpirationTime() > 365 ){
            throw new BaseException("sim过期时间异常范围");
        }
        if (rushPayFeeConfig.getApiCount() > 100000 ) {
            throw new BaseException("api调用次数异常范围");
        }
    }

    /**
     * 返回的定时任务类选择
     *
     * @param className 类名
     * @return 定时任务类
     */
    public Object classChoose(String className) {
        switch (className) {
            case "ActivityQuartz":
                return activityQuartz;
            case "BirthGiveQuartz":
                return birthGiveQuartz;
            case "ClearExpireCouponQuartz":
                return clearExpireCouponQuartz;
            case "LowBatteryReminderQuartz":
                return lowBatteryReminderQuartz;
            case "PointQuartz":
                return pointQuartz;
            case "ReconciliationQuartz":
                return reconciliationQuartz;
            case "SubAccountQuartz":
                return subAccountQuartz;
            case "SundryDataQuartz":
                return sundryDataQuartz;
            case "FinancialStatisticsQuartz":
                return financialStatisticsQuartz;
            default:
                throw new BaseException("className有误");
        }
    }

    /**
     * 方法执行
     *
     * @param quartzObject 定时任务类
     * @param methodName   方法名
     */
    Result executeMethod(Object quartzObject, String methodName) {
        Method[] Methods = quartzObject.getClass().getDeclaredMethods();
        for (Method method : Methods) {
            if (methodName.equals(method.getName())) {
                //空参执行
                try {
                    long start = System.currentTimeMillis();
                    log.info("手动执行定时任务开始");
                    method.invoke(quartzObject);
                    long time = System.currentTimeMillis() - start;
                    log.info("手动执行定时任务结束，耗时{}毫秒", time);
                    return Result.success("定时任务手动执行完成，耗时" + time + "毫秒");
                } catch (IllegalAccessException e) {
                    log.error(e.getMessage(), e);
                    throw new BaseException("没有访问权限");
                } catch (InvocationTargetException e) {
                    log.error(e.getMessage(), e);
                    throw new BaseException("执行方法发生异常");
                }
            }
        }
        return Result.error("methodName有误");
    }


}
